"""
旅游平台首页API
"""
from fastapi import APIRouter, Depends, HTTPException, status, Header
from sqlalchemy.orm import Session
from sqlalchemy import desc
from starlette.concurrency import run_in_threadpool
from typing import List
import asyncio
import logging

from utils.database import get_db
from Models.travel.models import Attraction, Banner, Category
from Models.travel.schemas import (
    HomePageResponse, AttractionInfo, BannerInfo, CategoryInfo,
    AttractionListResponse
)
from utils import JWTUtils
from utils.recommendation_system import collect_user_behavior

router = APIRouter(prefix="/travel", tags=["旅游平台"])
logger = logging.getLogger(__name__)

# 数据库查询超时时间（秒）
DB_QUERY_TIMEOUT = 5


@router.get("/categories", response_model=List[CategoryInfo], summary="获取全部分类")
async def list_categories(db: Session = Depends(get_db)):
    """
    获取所有启用的分类，按 sort 和 id 倒序。
    """
    def fetch_categories():
        try:
            return db.query(Category)\
                .filter(Category.is_active == True)\
                .order_by(Category.sort.desc(), Category.id.desc())\
                .all()
        except Exception:
            return []
    
    categories = await run_in_threadpool(fetch_categories)
    return [CategoryInfo.model_validate(c) for c in categories]

@router.get("/home", response_model=HomePageResponse, summary="获取首页数据")
async def get_home_page(db: Session = Depends(get_db)):
    """
    获取旅游平台首页数据
    包括：轮播图、分类、推荐景点、热门景点
    """
    try:
        async def fetch_data_with_timeout():
            """带超时的数据获取"""
            try:
                def fetch_data():
                    try:
                        # 获取轮播图
                        banners = db.query(Banner).filter(
                            Banner.is_active == True
                        ).order_by(Banner.sort.desc(), Banner.id.desc()).limit(5).all()
                        
                        # 获取分类
                        categories = db.query(Category).filter(
                            Category.is_active == True
                        ).order_by(Category.sort.desc(), Category.id.desc()).limit(10).all()
                        
                        # 获取推荐景点
                        recommended = db.query(Attraction).filter(
                            Attraction.is_active == True,
                            Attraction.is_recommended == True
                        ).order_by(desc(Attraction.rating), desc(Attraction.review_count)).limit(6).all()
                        
                        # 获取热门景点（按评分和评价数）
                        popular = db.query(Attraction).filter(
                            Attraction.is_active == True
                        ).order_by(desc(Attraction.rating), desc(Attraction.review_count)).limit(8).all()
                        
                        # 获取商家发布的景点（有merchant_id的景点）
                        merchant_attractions = db.query(Attraction).filter(
                            Attraction.is_active == True,
                            Attraction.merchant_id.isnot(None)  # 只获取有商家的景点
                        ).order_by(desc(Attraction.created_at), desc(Attraction.rating)).limit(10).all()
                        
                        return banners, categories, recommended, popular, merchant_attractions
                    except Exception as e:
                        # 如果表不存在或其他数据库错误，返回空数据
                        logger.error(f"数据库查询错误: {e}", exc_info=True)
                        return [], [], [], [], []
                
                # 使用asyncio.wait_for添加超时
                result = await asyncio.wait_for(
                    run_in_threadpool(fetch_data),
                    timeout=DB_QUERY_TIMEOUT
                )
                return result
            except asyncio.TimeoutError:
                logger.warning(f"首页数据查询超时（>{DB_QUERY_TIMEOUT}秒）")
                return [], [], [], [], []
            except Exception as e:
                logger.error(f"获取首页数据失败: {e}", exc_info=True)
                return [], [], [], [], []
        
        banners, categories, recommended, popular, merchant_attractions = await fetch_data_with_timeout()
        
        # 转换为响应模型
        return HomePageResponse(
            banners=[BannerInfo.model_validate(b) for b in banners] if banners else [],
            categories=[CategoryInfo.model_validate(c) for c in categories] if categories else [],
            recommended_attractions=[AttractionInfo.model_validate(a) for a in recommended] if recommended else [],
            popular_attractions=[AttractionInfo.model_validate(a) for a in popular] if popular else [],
            merchant_attractions=[AttractionInfo.model_validate(a) for a in merchant_attractions] if merchant_attractions else []
        )
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f"获取首页数据失败: {e}", exc_info=True)
        # 返回空数据而不是抛出异常，确保前端能正常接收响应
        return HomePageResponse(
            banners=[],
            categories=[],
            recommended_attractions=[],
            popular_attractions=[],
            merchant_attractions=[]
        )


@router.get("/attractions", response_model=AttractionListResponse, summary="获取景点列表")
async def get_attractions(
    page: int = 1,
    page_size: int = 10,
    type: str = None,
    category_id: int = None,
    category: str = None,
    city: str = None,
    keyword: str = None,
    min_price: float = None,
    max_price: float = None,
    sort_by: str = "composite",  # composite|rating|reviews|price|created
    sort_order: str = "desc",    # asc|desc
    db: Session = Depends(get_db)
):
    """
    获取景点列表
    支持分页、类型筛选、分类筛选、城市筛选、关键词搜索、价格区间、排序
    """
    
    def fetch_attractions():
        query = db.query(Attraction).filter(Attraction.is_active == True)
        
        # 类型筛选
        if type:
            query = query.filter(Attraction.type == type)
        
        # 分类筛选（通过分类名称匹配景点 tags）
        # 1) 优先使用分类ID查出分类名称
        if category_id:
            cat = db.query(Category).filter(
                Category.id == category_id,
                Category.is_active == True
            ).first()
            if cat and cat.name:
                query = query.filter(Attraction.tags.like(f"%{cat.name}%"))
        # 2) 直接传分类名称
        elif category:
            query = query.filter(Attraction.tags.like(f"%{category}%"))
        
        # 城市筛选
        if city:
            query = query.filter(Attraction.city == city)
        
        # 关键词搜索
        if keyword:
            query = query.filter(
                (Attraction.name.like(f"%{keyword}%")) |
                (Attraction.description.like(f"%{keyword}%"))
            )
        
        # 价格区间
        if min_price is not None:
            query = query.filter(Attraction.price >= min_price)
        if max_price is not None:
            query = query.filter(Attraction.price <= max_price)
        
        # 总数
        total = query.count()
        
        # 分页查询
        # 排序
        orderings = []
        sort_order_is_desc = (sort_order or "desc").lower() != "asc"
        if (sort_by or "composite") == "composite":
            # 推荐优先 + 评分 + 评价数 的组合
            orderings.append(desc(Attraction.is_recommended))
            orderings.append(desc(Attraction.rating))
            orderings.append(desc(Attraction.review_count))
        elif sort_by == "rating":
            orderings.append(desc(Attraction.rating) if sort_order_is_desc else Attraction.rating)
        elif sort_by == "reviews":
            orderings.append(desc(Attraction.review_count) if sort_order_is_desc else Attraction.review_count)
        elif sort_by == "price":
            orderings.append(desc(Attraction.price) if sort_order_is_desc else Attraction.price)
        elif sort_by == "created":
            orderings.append(desc(Attraction.created_at) if sort_order_is_desc else Attraction.created_at)
        else:
            # 默认组合排序
            orderings.append(desc(Attraction.is_recommended))
            orderings.append(desc(Attraction.rating))
            orderings.append(desc(Attraction.review_count))
        
        attractions = query.order_by(*orderings).offset((page - 1) * page_size).limit(page_size).all()
        
        return total, attractions
    
    total, attractions = await run_in_threadpool(fetch_attractions)
    
    return AttractionListResponse(
        total=total,
        page=page,
        page_size=page_size,
        attractions=[AttractionInfo.model_validate(a) for a in attractions]
    )


@router.get(
    "/categories/{category_id}/attractions",
    response_model=AttractionListResponse,
    summary="按分类获取景点列表"
)
async def get_attractions_by_category(
    category_id: int,
    page: int = 1,
    page_size: int = 10,
    city: str = None,
    keyword: str = None,
    db: Session = Depends(get_db)
):
    """
    便捷接口：通过分类ID拉取景点列表
    内部等价于 /travel/attractions?category_id=xx
    """
    return await get_attractions(
        page=page,
        page_size=page_size,
        type=None,
        category_id=category_id,
        category=None,
        city=city,
        keyword=keyword,
        db=db
    )


@router.get("/attractions/{attraction_id}", response_model=AttractionInfo, summary="获取景点详情")
async def get_attraction_detail(
    attraction_id: int,
    user_id: int = None,
    authorization: str = Header(None),
    db: Session = Depends(get_db)
):
    """
    获取景点详情（自动收集用户浏览行为）
    
    - **attraction_id**: 景点ID
    - **user_id**: 用户ID（可选，如果提供了Authorization header则从token获取）
    - **authorization**: Authorization header（可选）
    """
    def fetch_attraction():
        attraction = db.query(Attraction).filter(
            Attraction.id == attraction_id,
            Attraction.is_active == True
        ).first()
        return attraction
    
    attraction = await run_in_threadpool(fetch_attraction)
    
    if not attraction:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="景点不存在"
        )
    
    # 收集用户浏览行为（如果用户已登录）
    try:
        # 优先从Authorization header获取用户ID
        if authorization:
            try:
                if authorization.startswith("Bearer "):
                    token = authorization[7:]
                else:
                    token = authorization
                payload = JWTUtils.decode_access_token(token)
                if payload and payload.get("user_id"):
                    user_id = payload["user_id"]
            except:
                pass
        
        # 如果用户已登录，收集浏览行为
        if user_id:
            try:
                await run_in_threadpool(
                    collect_user_behavior,
                    db,
                    user_id,
                    attraction_id,
                    "view",
                    None
                )
            except Exception as e:
                # 记录错误但不影响详情页返回
                import logging
                logger = logging.getLogger(__name__)
                logger.warning(f"收集用户浏览行为失败: {e}")
    except:
        pass  # 忽略收集行为时的错误，不影响详情页功能
    
    return AttractionInfo.model_validate(attraction)



